﻿#region

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using JsMapper.BO;
using JsMapper.Helper;

#endregion

namespace JsMapper.Mappers
{
    public class Backbone : IJsModelMapper
    {
        public string GetJs(IJsModel model)
        {
            var parts = new List<string>();

            var defaults = GetDefaults(model);
            var defPart = string.Format("defaults: {{{0}}}", defaults);
            parts.Add(defPart);

            if (model.IdProperty != null)
            {
                var idPart = string.Format("idAttribute: '{0}'", model.IdProperty.Name);
                parts.Add(idPart);
            }

            if (!string.IsNullOrEmpty(model.Url))
            {
                var urlRoot = string.Format("urlRoot: '{0}'", model.Url);
                parts.Add(urlRoot);
            }

            if (model.Validations.Count > 0)
            {
                var valPart = GetValidation(model);
                parts.Add(valPart);
            }

            var allParts = string.Join(",", parts);
            return string.Format("Backbone.Model.extend({{{0}}})", allParts);
        }

        private string GetDefaults(IJsModel model)
        {
            var props = model.Properties.Select(
                x =>
                    {
                        var val = model.DefaultValues.ContainsKey(x)
                                      ? model.DefaultValues[x].Value.ToJsFormatted()
                                      : "''";
                        return string.Format("{0}:{1}", x.Name, val);
                    })
                             .ToList();


            return string.Join(",", props);
        }

        private string GetValidation(IJsModel model)
        {
            var allVals = new List<string>();

            foreach (var p in model.Validations)
            {
                var propVals = new List<string>();

                foreach (var v in p.Value)
                {
                    var valPart = new List<string>();

                    if (!string.IsNullOrEmpty(v.ErrorMessage)) valPart.Add(string.Format("msg: '{0}'", v.ErrorMessage));

                    var validator = GetValidator(v);
                    if (!string.IsNullOrEmpty(validator)) valPart.Add(validator);

                    var valItem = string.Format("{{{0}}}", string.Join(",", valPart));
                    propVals.Add(valItem);
                }

                var curPropVal = string.Format("{0}: [{1}]", p.Key.Name, string.Join(",", propVals));
                allVals.Add(curPropVal);
            }

            return string.Join(",", allVals);
        }

        private string GetValidator(ValidationAttribute v)
        {
            if (v is RequiredAttribute) return "required: true";

            var minAttr = v as MinLengthAttribute;
            if (minAttr != null) return string.Format("minLength: {0}", minAttr.Length);

            var maxAttr = v as MaxLengthAttribute;
            if (maxAttr != null) return string.Format("maxLength: {0}", maxAttr.Length);

            var rangeAttr = v as RangeAttribute;
            if (rangeAttr != null)
                return string.Format("rangeLength: [{0}, {1}]", rangeAttr.Minimum, rangeAttr.Maximum);

            if (v is EmailAddressAttribute) return "pattern: 'email'";
            if (v is UrlAttribute) return "pattern: 'url'";

            return string.Empty;
        }
    }
}